/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "tim.h"
#include "usb_device.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <errno.h>
#include <string.h>
#include <stdbool.h>
#include "usbd_cdc_if.h"
#include "stm32f1xx_hal_flash.h"  // 改对应系列的头文件
#include "stm32f1xx_hal_flash_ex.h"

#include "pressure_sensor.h"//压力信号采集

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

uint8_t get_data_flag = 0;//USB收到数据标志位
uint8_t buf[256] = { 0 };//USB接收到的内容保存数组
uint8_t data_nums = 0;//USB接收到数据的

char* ptr = NULL;

char flash_buff[32] = { 0 };

int threshold=0; //保存阈值的变量

#if 0
char write_str[50] = { 0 };
char read_str[50] = { 0 };
#endif

uint32_t str_addr;//地址

int read_num;//读取阈值变量
int write_int;//存储阈值变量
char threshold_back[32]={0};//存储读取返回的阈值

/*预设返回提示内容数组*/
uint8_t str_of_success[] = { "Threshold set successfully. " };//设置阈值成功
uint8_t str_of_fail[] = { "Failed to set threshold." };//设置阈值失败
uint8_t str_of_No_parameters[]={"No parameters, please enter the threshold parameter."};//无参数
/******************************/

// 写入Flash的扇区1（地址为0x08004000）
#define FLASH_USER_START_ADDR  0x0801F000  // 用户Flash起始地址
#define FLASH_USER_END_ADDR    0x0801FFFF  // 用户Flash结束地址

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
//PressureSensor_t pressure_sensor;
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */



/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

#if 1
//flash擦除函数
HAL_StatusTypeDef FLASH_Erase_Sector(uint32_t start_addr, uint32_t end_addr)
{
	// 参数检查
	if (start_addr < FLASH_BASE || end_addr < start_addr)
	{
		return HAL_ERROR;
	}

	// 地址页对齐
	start_addr = start_addr & ~(FLASH_PAGE_SIZE - 1);
	end_addr = end_addr & ~(FLASH_PAGE_SIZE - 1);

	HAL_StatusTypeDef status = HAL_ERROR;
	FLASH_EraseInitTypeDef erase_init;
	uint32_t page_error = 0;

	// 计算需要擦除的页
	uint32_t start_page = (start_addr - FLASH_BASE) / FLASH_PAGE_SIZE;
	uint32_t end_page = (end_addr - FLASH_BASE) / FLASH_PAGE_SIZE;
	uint32_t page_count = end_page - start_page + 1;

	// 解锁Flash
	if (HAL_FLASH_Unlock() != HAL_OK)
	{
		Error_Handler();
	}

	// 清除所有挂起的标志
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR);

	// 配置擦除参数
	erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
	erase_init.PageAddress = start_addr;
	erase_init.NbPages = page_count;

	// 执行擦除
	status = HAL_FLASHEx_Erase(&erase_init, &page_error);

	// 锁住Flash
	HAL_FLASH_Lock();

	return status;
}
#endif

//写flash函数
#if 1
HAL_StatusTypeDef Flash_Write(uint32_t startaddress, void* data, uint32_t size)
{
	// 参数检查
	if (!data || size == 0 || startaddress % 4 != 0)
	{
		return HAL_ERROR;
	}

	HAL_StatusTypeDef status = HAL_OK;
	uint32_t i;
	const uint32_t* data_ptr = (const uint32_t*)data;
	uint32_t word_count = (size + 3) / 4; // 计算需要写入的32位字数

	if (HAL_FLASH_Unlock() != HAL_OK)//解锁flash
	{
		return HAL_ERROR;
	}

	// 清除标志
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR);

	//编程Flash
	for (i = 0; i < word_count; i++)
	{
		status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, startaddress + (i * 4), data_ptr[i]);
		if (status != HAL_OK)
		{
			break;
		}
	}
	HAL_FLASH_Lock();//锁定Flash

	return status;
}

#else

#define StartServerManageFlashAddress    ((u32)0x08036000)

void FLASH_WriteMoreData(uint32_t startAddress, uint16_t* writeData, uint16_t countToWrite)
{
	uint32_t offsetAddress = startAddress - FLASH_BASE;               //计算去掉0X08000000后的实际偏移地址
	uint32_t sectorPosition = offsetAddress / SECTOR_SIZE;            //计算扇区地址，对于STM32F103VET6为0~255
	uint32_t sectorStartAddress = sectorPosition * SECTOR_SIZE + FLASH_BASE;    //对应扇区的首地址
	uint16_t dataIndex;

	if (startAddress < FLASH_BASE || ((startAddress + countToWrite * 2) >= (FLASH_BASE + SECTOR_SIZE * FLASH_SIZE)))
	{
		return;//非法地址
	}
	HAL_FLASH_Unlock();         //解锁写保护

	FLASH_ErasePage(sectorStartAddress);//擦除这个扇区

	for (dataIndex = 0; dataIndex < countToWrite; dataIndex++)
	{
		FLASH_ProgramHalfWord(startAddress + dataIndex * 2, writeData[dataIndex]);
	}

	HAL_FLASH_Lock();//上锁写保护
}

#endif
//读Flash函数
HAL_StatusTypeDef Flash_Read(uint32_t address, void* data, uint32_t size)
{
	if (!data || size == 0)
	{
		return HAL_ERROR;
	}

	// 直接内存拷贝
	memcpy(data, (void*)address, size);
	return HAL_OK;
}

//写入flash函数
void Flash_0peration_Example(int* write_num)//num为阈值
{
	HAL_StatusTypeDef status;
#if 1
	//读整形
	status = FLASH_Erase_Sector(FLASH_USER_START_ADDR, FLASH_USER_START_ADDR + 3);//擦除flash
	if (status == HAL_OK)
	{
		status = Flash_Write(FLASH_USER_START_ADDR, write_num, sizeof(write_num));//写入flash
		if (status == HAL_OK)
		{
			Flash_Read(FLASH_USER_START_ADDR, &read_num, sizeof(read_num));//再读取一次
			if (read_num == *write_num)//判断读取的和写入的是否是一样的
			{
				//一样的 返回正确
				CDC_Transmit_FS((uint8_t*)str_of_success, strlen((char *)str_of_success));
			}
			else
			{
				//不一样的 返回错误
				CDC_Transmit_FS((uint8_t*)str_of_fail, strlen((char *)str_of_fail));
			}
		}
	}
#elif 0
	//读取字符串 CF+RESET:将falsh中保存的重量阈值清零	##	CF+SET=%d:设置flash中保存的重量阈值为%d

	// 擦除足够的空间（注意地址对齐）
	str_addr = FLASH_USER_START_ADDR; // 偏移一些地址
	status = FLASH_Erase_Sector(str_addr, str_addr + strlen(write_str) + 1);
	if (status == HAL_OK)
	{
		// 写入字符串
		status = Flash_Write(str_addr, write_str, strlen(write_str) + 1);
		if (status == HAL_OK)
		{
			// 读取字符串
			Flash_Read(str_addr, read_str, strlen(write_str) + 1);
			if (strcmp(write_str, read_str) == 0)
			{
				char msg[50];
				sprintf(msg, "String write/read success: %s\r\n", read_str);
				CDC_Transmit_FS((uint8_t*)msg, strlen(msg));
				CDC_Transmit_FS((uint8_t*)sendbuff3, strlen(sendbuff3));
			}
			CDC_Transmit_FS((uint8_t*)"set success", strlen("set success"));//设置成功
		}
		else
		{
			CDC_Transmit_FS((uint8_t*)"set failure", strlen("set failure"));
		}
	}
#endif
}
/************/

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USB_DEVICE_Init();
  MX_TIM6_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim6);

	// 初始化压力传感器（包括滤波器）
	PressureSensor_Init();

	Start_ADC_Sampling();//开启DMA-ADC转换
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	while (1)
	{
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		//USB虚拟串口
		#if 1
		
		if (get_data_flag)//如果USB收到了数据
		{
			/*******************/
			if (strstr((char*)buf, "CF+RESET") != NULL)//检索到CF+RESET 清除阈值，设为0
			{
				//写入flash中为0
				threshold=0;//设置阈值为0
				Flash_0peration_Example(&threshold);//参数是阈值
			}
			/*******************/
			else if (strstr((char*)buf, "CF+SET=") != NULL)//检索到CF+SET= 设置阈值，值为“=”后边的字符型值
			{
				char *num=strchr((char*)buf, '=');//再检索‘=’
				if(num!=NULL)
				{
					num+=1;//地址偏移一个
					while(*num ==' ')
						num++;
					
					if(*num == '\0' || *num == '\r' || *num == '\n')//如果此时的内容是'\0'
					{
						//未输入阈值参数
						CDC_Transmit_FS((uint8_t*)str_of_No_parameters, strlen((char *)str_of_No_parameters));
					}
					else
					{
						char *endptr;
						long temp_threshold;
						
						errno=0;
						temp_threshold = strtol(num,&endptr,10);
						
						if(endptr == num)
						{
							// 没有数字被转换
               CDC_Transmit_FS((uint8_t*)">No valid number\r\n", 18);
						}
						else if(*endptr != '\0' && *endptr != '\r' && *endptr != '\n' && *endptr !=' ')
						{
							// 有无效字符
							char error_msg[50];
							snprintf(error_msg, sizeof(error_msg), ">Invalid char: %s\r\n", endptr);
							CDC_Transmit_FS((uint8_t*)error_msg, strlen(error_msg));
						}
//						else if(errno == ERANGE || temp_threshold > INT_MAX || temp_threshold < INT_MIN)
//						{
//							//阈值超出范围 预留
//						}
						else
						{
							  // 转换成功
                threshold = (int)temp_threshold;
                Flash_0peration_Example(&threshold);
                
                // 返回成功信息
                char success_msg[50];
                snprintf(success_msg, sizeof(success_msg), ">SET OK: %d\r\n", threshold);
                CDC_Transmit_FS((uint8_t*)success_msg, strlen(success_msg));
						}
					}
				}
			}
			/********************/
			else if(strstr((char*)buf, "CF+READ") != NULL)//读取参数
			{
				//调用一个读取的函数
				;//读取一次 这里需要坐健壮性增强
				if(Flash_Read(FLASH_USER_START_ADDR, &read_num, sizeof(read_num))==HAL_ERROR)
				{
					//如果等于错误，怎么能
				}
				else
				{
					memset(threshold_back,0,sizeof(threshold_back));//先清空
					sprintf(threshold_back,"The threshold is:%d.\n",read_num);//整合字符串
					CDC_Transmit_FS((uint8_t*)threshold_back, strlen(threshold_back));
				}

			}
			get_data_flag = 0;
		}
		
		#endif
		
		//压力采集
		#if 1
		
		Process_ADC_Data();//获取压力值
		
		#endif
		
	}
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_USB;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
	/* User can add his own implementation to report the HAL error return state */
	__disable_irq();
	while (1)
	{
	}
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
	/* User can add his own implementation to report the file name and line number,
	   ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
